using Microsoft.AspNetCore.Mvc;
using ConsoleApi.Models;
using ConsoleApi.Services.Interfaces;
using System.Text.Json;

namespace ConsoleApi.Controllers;

/// <summary>
/// 增强版天气控制器
/// </summary>
[ApiController]
[Route("api/[controller]")]
public class EnhancedWeatherController : ControllerBase
{
    private readonly IRealWeatherService _weatherService;
    private readonly ILogger<EnhancedWeatherController> _logger;

    public EnhancedWeatherController(IRealWeatherService weatherService, ILogger<EnhancedWeatherController> logger)
    {
        _weatherService = weatherService;
        _logger = logger;
    }

    /// <summary>
    /// 获取增强版天气信息
    /// </summary>
    [HttpGet("enhanced/{city}")]
    public async Task<IActionResult> GetEnhancedWeather(string city)
    {
        try
        {
            var weatherData = await _weatherService.GetWeatherByCityAsync(city);
            
            // 构建增强版天气数据
            var enhancedWeather = new EnhancedWeatherData
            {
                BasicWeather = weatherData,
                AirQuality = await GetAirQualityAsync(city),
                UVIndex = await GetUVIndexAsync(city),
                LifeIndices = await GetLifeIndicesAsync(weatherData),
                WeatherTrends = await GetWeatherTrendsAsync(weatherData),
                Alerts = await GetWeatherAlertsAsync(city)
            };

            return Ok(new { success = true, data = enhancedWeather });
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取增强版天气信息失败: {City}", city);
            return BadRequest(new { success = false, error = ex.Message });
        }
    }

    /// <summary>
    /// 获取多城市天气对比
    /// </summary>
    [HttpGet("compare")]
    public async Task<IActionResult> GetMultiCityWeather([FromQuery] string[] cities)
    {
        try
        {
            if (cities == null || cities.Length == 0)
            {
                return BadRequest(new { success = false, error = "请提供城市列表" });
            }

            var multiCityWeather = new List<CityWeatherInfo>();
            
            foreach (var city in cities.Take(5)) // 最多支持5个城市
            {
                try
                {
                    var weatherData = await _weatherService.GetWeatherByCityAsync(city);
                    multiCityWeather.Add(new CityWeatherInfo
                    {
                        City = city,
                        WeatherData = weatherData,
                        AirQuality = await GetAirQualityAsync(city),
                        LifeIndices = await GetLifeIndicesAsync(weatherData)
                    });
                }
                catch (Exception ex)
                {
                    _logger.LogWarning(ex, "获取城市 {City} 天气失败", city);
                    // 继续处理其他城市
                }
            }

            return Ok(new { success = true, data = multiCityWeather });
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取多城市天气对比失败");
            return BadRequest(new { success = false, error = ex.Message });
        }
    }

    /// <summary>
    /// 获取天气趋势分析
    /// </summary>
    [HttpGet("trends/{city}")]
    public async Task<IActionResult> GetWeatherTrends(string city, [FromQuery] int days = 7)
    {
        try
        {
            var weatherData = await _weatherService.GetWeatherByCityAsync(city);
            var trends = await GetWeatherTrendsAsync(weatherData, days);
            
            return Ok(new { success = true, data = trends });
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取天气趋势分析失败: {City}", city);
            return BadRequest(new { success = false, error = ex.Message });
        }
    }

    /// <summary>
    /// 获取生活指数建议
    /// </summary>
    [HttpGet("life-indices/{city}")]
    public async Task<IActionResult> GetLifeIndices(string city)
    {
        try
        {
            var weatherData = await _weatherService.GetWeatherByCityAsync(city);
            var lifeIndices = await GetLifeIndicesAsync(weatherData);
            
            return Ok(new { success = true, data = lifeIndices });
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取生活指数失败: {City}", city);
            return BadRequest(new { success = false, error = ex.Message });
        }
    }

    /// <summary>
    /// 获取7天天气预报
    /// </summary>
    [HttpGet("forecast/{city}")]
    public async Task<IActionResult> GetWeatherForecast(string city)
    {
        try
        {
            var weatherData = await _weatherService.GetWeatherByCityAsync(city);
            
            if (weatherData.Forecast == null || weatherData.Forecast.Count == 0)
            {
                return BadRequest(new { success = false, error = "无法获取预报数据" });
            }

            // 获取7天预报数据
            var forecast = weatherData.Forecast.Take(7).ToList();
            
            // 构建详细的预报数据
            var detailedForecast = forecast.Select((day, index) => new
            {
                Date = day.Date.ToString("yyyy-MM-dd"),
                DayOfWeek = GetDayOfWeek(day.Date.ToString("yyyy-MM-dd")),
                Weather = day.Text,
                MaxTemp = day.MaxTemp,
                MinTemp = day.MinTemp,
                Humidity = day.Humidity,
                WindSpeed = day.WindSpeed,
                WindDir = day.WindDir,
                Pressure = day.Pressure,
                Visibility = day.Visibility,
                Sunrise = day.Sunrise,
                Sunset = day.Sunset,
                UVIndex = GetUVIndexForDay(day.MaxTemp, day.Text),
                ProductionImpact = GetProductionImpact(day),
                Recommendations = GetDailyRecommendations(day)
            }).ToList();

            return Ok(new { success = true, data = detailedForecast });
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取7天天气预报失败: {City}", city);
            return BadRequest(new { success = false, error = ex.Message });
        }
    }

    /// <summary>
    /// 获取指定日期的24小时详细预报
    /// </summary>
    [HttpGet("forecast/{city}/daily/{date}")]
    public async Task<IActionResult> GetDailyDetailedForecast(string city, string date)
    {
        try
        {
            var weatherData = await _weatherService.GetWeatherByCityAsync(city);
            
            if (weatherData.Forecast == null || weatherData.Forecast.Count == 0)
            {
                return BadRequest(new { success = false, error = "无法获取预报数据" });
            }

            // 查找指定日期的预报
            var targetDate = DateTime.Parse(date);
            var dayForecast = weatherData.Forecast.FirstOrDefault(f => 
                f.Date.Date == targetDate.Date);

            if (dayForecast == null)
            {
                return BadRequest(new { success = false, error = "未找到指定日期的预报数据" });
            }

            // 生成24小时详细预报
            var hourlyForecast = GenerateHourlyForecast(dayForecast);
            
            var detailedDay = new
            {
                Date = dayForecast.Date.ToString("yyyy-MM-dd"),
                DayOfWeek = GetDayOfWeek(dayForecast.Date.ToString("yyyy-MM-dd")),
                Weather = dayForecast.Text,
                MaxTemp = dayForecast.MaxTemp,
                MinTemp = dayForecast.MinTemp,
                Humidity = dayForecast.Humidity,
                WindSpeed = dayForecast.WindSpeed,
                WindDir = dayForecast.WindDir,
                Pressure = dayForecast.Pressure,
                Visibility = dayForecast.Visibility,
                Sunrise = dayForecast.Sunrise,
                Sunset = dayForecast.Sunset,
                HourlyForecast = hourlyForecast,
                ProductionImpact = GetProductionImpact(dayForecast),
                Recommendations = GetDailyRecommendations(dayForecast)
            };

            return Ok(new { success = true, data = detailedDay });
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取日期详细预报失败: {City}, {Date}", city, date);
            return BadRequest(new { success = false, error = ex.Message });
        }
    }

    #region 私有方法

    /// <summary>
    /// 获取空气质量信息
    /// </summary>
    private Task<AirQualityInfo> GetAirQualityAsync(string city)
    {
        // 这里应该调用真实的空气质量API
        // 目前使用模拟数据
        var random = new Random();
        var aqi = random.Next(30, 150);
        
        var result = new AirQualityInfo
        {
            AQI = aqi,
            Level = GetAQILevel(aqi),
            PM25 = random.Next(10, 80),
            PM10 = random.Next(20, 120),
            NO2 = random.Next(10, 60),
            SO2 = random.Next(5, 40),
            CO = random.Next(500, 2000),
            O3 = random.Next(20, 120)
        };
        
        return Task.FromResult(result);
    }

    /// <summary>
    /// 获取紫外线指数
    /// </summary>
    private Task<UVIndexInfo> GetUVIndexAsync(string city)
    {
        var random = new Random();
        var uvi = random.Next(1, 12);
        
        var result = new UVIndexInfo
        {
            Index = uvi,
            Level = GetUVLevel(uvi),
            Risk = GetUVRisk(uvi),
            ProtectionAdvice = GetUVProtectionAdvice(uvi)
        };
        
        return Task.FromResult(result);
    }

    /// <summary>
    /// 获取生活指数
    /// </summary>
    private Task<LifeIndicesInfo> GetLifeIndicesAsync(WeatherData weatherData)
    {
        if (weatherData.Current == null)
        {
            return Task.FromResult(new LifeIndicesInfo());
        }

        var temp = weatherData.Current.Temp;
        var humidity = weatherData.Current.Humidity;
        var windSpeed = weatherData.Current.WindSpeed;
        var weatherText = weatherData.Current.Text;

        var result = new LifeIndicesInfo
        {
            Clothing = GetClothingAdvice(temp),
            Exercise = GetExerciseAdvice(temp, weatherText),
            Umbrella = GetUmbrellaAdvice(weatherText),
            CarWash = GetCarWashAdvice(weatherText),
            Comfort = GetComfortLevel(temp, humidity),
            Travel = GetTravelAdvice(weatherText, windSpeed)
        };
        
        return Task.FromResult(result);
    }

    /// <summary>
    /// 获取天气趋势
    /// </summary>
    private Task<WeatherTrendsInfo> GetWeatherTrendsAsync(WeatherData weatherData, int days = 7)
    {
        if (weatherData.Forecast == null || weatherData.Forecast.Count == 0)
        {
            return Task.FromResult(new WeatherTrendsInfo());
        }

        var temps = weatherData.Forecast.Take(days).Select(f => (double)f.MaxTemp).ToList();
        var humidities = weatherData.Forecast.Take(days).Select(f => (double)f.Humidity).ToList();
        var windSpeeds = weatherData.Forecast.Take(days).Select(f => (double)f.WindSpeed).ToList();

        var result = new WeatherTrendsInfo
        {
            TemperatureTrend = AnalyzeTrend(temps),
            HumidityTrend = AnalyzeTrend(humidities),
            WindSpeedTrend = AnalyzeTrend(windSpeeds),
            ChangeAmplitude = CalculateAmplitude(temps),
            PredictionAdvice = GeneratePredictionAdvice(temps, humidities, windSpeeds)
        };
        
        return Task.FromResult(result);
    }

    /// <summary>
    /// 获取天气预警
    /// </summary>
    private Task<List<WeatherAlertInfo>> GetWeatherAlertsAsync(string city)
    {
        // 模拟天气预警数据
        var alerts = new List<WeatherAlertInfo>();
        var random = new Random();

        if (random.Next(100) < 30) // 30%概率有大风预警
        {
            alerts.Add(new WeatherAlertInfo
            {
                Id = Guid.NewGuid().ToString(),
                Level = "warning",
                Type = "大风预警",
                Title = "大风黄色预警",
                Description = "预计未来6小时内将出现6-8级大风，请注意防范",
                Location = city,
                Time = DateTime.Now,
                ValidUntil = DateTime.Now.AddHours(6),
                ProtectionAdvice = new List<string>
                {
                    "关好门窗，加固围板、棚架、广告牌等易被风吹动的搭建物",
                    "妥善安置易受大风影响的室外物品",
                    "行人注意尽量少骑自行车，刮风时不要在广告牌、临时搭建物等下面逗留"
                }
            });
        }

        if (random.Next(100) < 40) // 40%概率有降水提醒
        {
            alerts.Add(new WeatherAlertInfo
            {
                Id = Guid.NewGuid().ToString(),
                Level = "info",
                Type = "降水提醒",
                Title = "降水提醒",
                Description = "今日有阵雨，出门请携带雨具",
                Location = city,
                Time = DateTime.Now,
                ValidUntil = DateTime.Now.AddHours(24),
                ProtectionAdvice = new List<string>
                {
                    "出门携带雨伞或雨衣",
                    "注意路面湿滑，谨慎驾驶",
                    "避免在雷雨天气进行户外活动"
                }
            });
        }

        return Task.FromResult(alerts);
    }

    #endregion

    #region 辅助方法

    private string GetAQILevel(int aqi)
    {
        return aqi switch
        {
            <= 50 => "优",
            <= 100 => "良",
            <= 150 => "轻度污染",
            <= 200 => "中度污染",
            <= 300 => "重度污染",
            _ => "严重污染"
        };
    }

    private string GetUVLevel(int uvi)
    {
        return uvi switch
        {
            <= 2 => "低",
            <= 5 => "中等",
            <= 7 => "高",
            <= 10 => "很高",
            _ => "极高"
        };
    }

    private string GetUVRisk(int uvi)
    {
        return uvi switch
        {
            <= 2 => "低风险",
            <= 5 => "中等风险",
            <= 7 => "高风险",
            <= 10 => "很高风险",
            _ => "极高风险"
        };
    }

    private string GetUVProtectionAdvice(int uvi)
    {
        return uvi switch
        {
            <= 2 => "无需防护",
            <= 5 => "建议涂抹防晒霜",
            <= 7 => "涂抹防晒霜，戴帽子",
            <= 10 => "涂抹防晒霜，戴帽子，穿长袖",
            _ => "避免外出，必须外出时全副防护"
        };
    }

    private string GetClothingAdvice(double temp)
    {
        return temp switch
        {
            >= 25 => "建议着短袖、短裙、短裤等清凉衣物",
            >= 20 => "建议着长袖衬衫、单裤等服装",
            >= 15 => "建议着薄外套、长裤等服装",
            >= 10 => "建议着厚外套、毛衣等服装",
            >= 5 => "建议着棉衣、羽绒服等厚外套",
            _ => "建议着厚棉衣、羽绒服等保暖衣物"
        };
    }

    private string GetExerciseAdvice(double temp, string weatherText)
    {
        if (weatherText.Contains("雨") || weatherText.Contains("雪"))
            return "不建议户外运动，可在室内进行适当运动";
        
        return temp switch
        {
            >= 30 or <= 0 => "不建议户外运动，可在室内进行适当运动",
            >= 20 and <= 25 => "天气适宜，非常适合户外运动",
            _ => "天气较适宜，建议适当运动，注意保暖"
        };
    }

    private string GetUmbrellaAdvice(string weatherText)
    {
        if (weatherText.Contains("雨") || weatherText.Contains("雪"))
            return "建议携带雨伞";
        if (weatherText.Contains("雾") || weatherText.Contains("霾"))
            return "建议携带口罩";
        return "无需携带雨伞";
    }

    private string GetCarWashAdvice(string weatherText)
    {
        if (weatherText.Contains("雨") || weatherText.Contains("雪"))
            return "不适宜洗车";
        if (weatherText.Contains("雾") || weatherText.Contains("霾"))
            return "较不适宜洗车";
        return "较适宜洗车";
    }

    private string GetComfortLevel(double temp, int humidity)
    {
        if (temp >= 20 && temp <= 26 && humidity >= 40 && humidity <= 70)
            return "舒适";
        if (temp >= 18 && temp <= 28 && humidity >= 30 && humidity <= 80)
            return "较舒适";
        if (temp >= 15 && temp <= 30)
            return "一般";
        return "不舒适";
    }

    private string GetTravelAdvice(string weatherText, double windSpeed)
    {
        if (weatherText.Contains("雨") || weatherText.Contains("雪"))
            return "有降水天气，出行请携带雨具，注意交通安全";
        if (windSpeed > 10)
            return "风力较大，出行注意安全，避免高空作业";
        return "天气晴好，适合出行，注意防晒";
    }

    private string AnalyzeTrend(List<double> values)
    {
        if (values.Count < 2) return "数据不足";
        
        var firstHalf = values.Take(values.Count / 2).Average();
        var secondHalf = values.Skip(values.Count / 2).Average();
        
        if (secondHalf > firstHalf * 1.1) return "上升趋势";
        if (secondHalf < firstHalf * 0.9) return "下降趋势";
        return "相对稳定";
    }

    private string CalculateAmplitude(List<double> values)
    {
        if (values.Count == 0) return "数据不足";
        
        var max = values.Max();
        var min = values.Min();
        var amplitude = max - min;
        
        return amplitude switch
        {
            < 5 => "变化很小",
            < 15 => "变化较小",
            < 30 => "变化中等",
            _ => "变化较大"
        };
    }

    private string GeneratePredictionAdvice(List<double> temps, List<double> humidities, List<double> windSpeeds)
    {
        var tempTrend = AnalyzeTrend(temps);
        var humidityTrend = AnalyzeTrend(humidities);
        var windTrend = AnalyzeTrend(windSpeeds);

        if (tempTrend == "上升趋势")
            return "温度将持续升高，注意防暑降温";
        if (tempTrend == "下降趋势")
            return "温度将持续下降，注意保暖";
        if (windTrend == "上升趋势")
            return "风力将增强，注意防风";
        if (humidityTrend == "上升趋势")
            return "湿度将增加，注意防潮";

        return "天气相对稳定，可正常安排活动";
    }

    /// <summary>
    /// 获取星期几
    /// </summary>
    private string GetDayOfWeek(string dateString)
    {
        if (DateTime.TryParse(dateString, out var date))
        {
            return date.DayOfWeek switch
            {
                DayOfWeek.Sunday => "周日",
                DayOfWeek.Monday => "周一",
                DayOfWeek.Tuesday => "周二",
                DayOfWeek.Wednesday => "周三",
                DayOfWeek.Thursday => "周四",
                DayOfWeek.Friday => "周五",
                DayOfWeek.Saturday => "周六",
                _ => "未知"
            };
        }
        return "未知";
    }

    /// <summary>
    /// 获取每日紫外线指数
    /// </summary>
    private int GetUVIndexForDay(double maxTemp, string weather)
    {
        var random = new Random();
        if (weather.Contains("晴") || weather.Contains("少云"))
        {
            return random.Next(6, 12); // 晴天紫外线较高
        }
        else if (weather.Contains("多云"))
        {
            return random.Next(3, 8); // 多云紫外线中等
        }
        else
        {
            return random.Next(1, 5); // 阴天紫外线较低
        }
    }

    /// <summary>
    /// 获取生产影响分析
    /// </summary>
    private object GetProductionImpact(ForecastDay day)
    {
        return new
        {
            TemperatureImpact = GetTemperatureImpact(day.MaxTemp),
            PrecipitationImpact = GetPrecipitationImpact(day.Text),
            WindImpact = GetWindImpact(day.WindSpeed),
            OverallRisk = GetOverallRisk(day)
        };
    }

    /// <summary>
    /// 获取每日生产建议
    /// </summary>
    private List<string> GetDailyRecommendations(ForecastDay day)
    {
        var recommendations = new List<string>();

        if (day.MaxTemp > 35)
        {
            recommendations.Add("暂停户外作业，避免中暑");
            recommendations.Add("调整工作时间至早晚凉爽时段");
            recommendations.Add("增加员工休息频率");
        }
        else if (day.MaxTemp < 5)
        {
            recommendations.Add("加强保暖防护装备");
            recommendations.Add("检查设备防冻状态");
            recommendations.Add("选择温度相对较高的时段作业");
        }

        if (day.Text.Contains("雨") || day.Text.Contains("雪"))
        {
            recommendations.Add("暂停户外高风险作业");
            recommendations.Add("加强货物防护和运输安全");
            recommendations.Add("准备应急响应预案");
        }

        if (day.WindSpeed > 15)
        {
            recommendations.Add("暂停高空作业");
            recommendations.Add("加强安全防护措施");
            recommendations.Add("注意设备稳定性");
        }

        if (recommendations.Count == 0)
        {
            recommendations.Add("天气适宜，可正常进行生产活动");
            recommendations.Add("保持常规安全措施");
            recommendations.Add("定期检查设备状态");
        }

        return recommendations;
    }

    /// <summary>
    /// 生成24小时详细预报
    /// </summary>
    private List<object> GenerateHourlyForecast(ForecastDay day)
    {
        var hourlyForecast = new List<object>();
        var random = new Random();

        for (int hour = 0; hour < 24; hour++)
        {
            var hourString = hour.ToString("00") + ":00";
            var temp = random.Next((int)day.MinTemp, (int)day.MaxTemp + 1);
            var humidity = random.Next(40, 80);
            var windSpeed = random.Next(5, 25);
            var precipitation = random.Next(0, 100);

            hourlyForecast.Add(new
            {
                Time = hourString,
                Icon = GetWeatherIcon(day.Text),
                Temp = temp,
                Weather = day.Text,
                Humidity = humidity,
                WindSpeed = windSpeed,
                Precipitation = precipitation
            });
        }

        return hourlyForecast;
    }

    /// <summary>
    /// 获取天气图标
    /// </summary>
    private string GetWeatherIcon(string weather)
    {
        return weather switch
        {
            var w when w.Contains("晴") => "☀️",
            var w when w.Contains("多云") => "⛅",
            var w when w.Contains("阴") => "☁️",
            var w when w.Contains("雨") => "🌧️",
            var w when w.Contains("雪") => "❄️",
            var w when w.Contains("雾") => "🌫️",
            var w when w.Contains("霾") => "😷",
            _ => "🌤️"
        };
    }

    /// <summary>
    /// 获取温度影响
    /// </summary>
    private string GetTemperatureImpact(double temp)
    {
        return temp switch
        {
            > 35 => "高温天气，严重影响户外作业，建议暂停",
            > 30 and <= 35 => "温度较高，建议调整作业时间，避开正午",
            < 0 => "严寒天气，暂停户外作业，加强保暖措施",
            < 5 and >= 0 => "低温天气，注意防寒保暖，检查设备防冻",
            _ => "温度适宜，可正常进行户外作业"
        };
    }

    /// <summary>
    /// 获取降水影响
    /// </summary>
    private string GetPrecipitationImpact(string weather)
    {
        if (weather.Contains("雨") || weather.Contains("雪"))
        {
            return "降水天气，暂停户外作业，注意防滑防摔";
        }
        return "无降水，适合户外作业";
    }

    /// <summary>
    /// 获取风力影响
    /// </summary>
    private string GetWindImpact(double windSpeed)
    {
        return windSpeed switch
        {
            > 20 => "大风天气，暂停高空作业，注意安全",
            > 15 => "风力较大，注意高空作业安全",
            > 10 => "风力适中，可正常作业",
            _ => "风力较小，适合各种作业"
        };
    }

    /// <summary>
    /// 获取整体风险等级
    /// </summary>
    private string GetOverallRisk(ForecastDay day)
    {
        var riskScore = 0;

        if (day.MaxTemp > 35 || day.MaxTemp < 0) riskScore += 3;
        else if (day.MaxTemp > 30 || day.MaxTemp < 5) riskScore += 2;

        if (day.Text.Contains("雨") || day.Text.Contains("雪")) riskScore += 2;
        if (day.WindSpeed > 15) riskScore += 2;

        return riskScore switch
        {
            >= 5 => "高风险",
            >= 3 => "中风险",
            >= 1 => "低风险",
            _ => "无风险"
        };
    }

    #endregion
} 